package com.yufubao.service.service.management.authorization.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yufubao.framework.constant.SystemConstants;
import com.yufubao.framework.enums.CommonExceptionEnum;
import com.yufubao.framework.exception.BaseException;
import com.yufubao.framework.result.PageUtils;
import com.yufubao.framework.result.ResponseResult;
import com.yufubao.framework.util.CopyBean;
import com.yufubao.framework.util.SecurityUtils;
import com.yufubao.framework.util.page.Query;
import com.yufubao.model.dto.management.sys.Route;
import com.yufubao.model.dto.management.sys.SaveMenuDto;
import com.yufubao.model.dto.management.sys.UpdateMenuDto;
import com.yufubao.model.pojo.management.authorization.ManagerEntity;
import com.yufubao.model.pojo.management.authorization.MenuEntity;
import com.yufubao.model.vo.management.authorization.MenuVo;
import com.yufubao.model.vo.management.authorization.RoutersVo;
import com.yufubao.model.vo.management.sys.MenuTreeSelectVO;
import com.yufubao.model.vo.management.sys.RoleMenuTreeselectVO;
import com.yufubao.service.mapper.management.authorization.MenuDao;
import com.yufubao.service.service.management.authorization.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuDao, MenuEntity> implements MenuService {

    @Autowired
    private MenuDao menuDao;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MenuEntity> page = this.page(
                new Query<MenuEntity>().getPage(params),
                new QueryWrapper<MenuEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * @param managerId
     * @return java.util.List<java.lang.String>
     * @description 根据用户id查询权限信息
     * @author zhangyiheng
     * @date 2024/9/4 16:04
     */
    @Override
    public List<String> selectPermsByManagerId(Long managerId) {
        //如果是管理员，返回所有的权限
        if (managerId == 1L) {
            LambdaQueryWrapper<MenuEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(MenuEntity::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);
            wrapper.eq(MenuEntity::getStatus, SystemConstants.STATUS_STRING);
            List<MenuEntity> menus = list(wrapper);
            List<String> perms = menus.stream()
                    .map(MenuEntity::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //否则返回所具有的权限
        return getBaseMapper().selectPermsByManagerId(managerId);
    }

    /**
     * @param
     * @return java.util.List<com.yufubao.model.vo.bms.MenuVo>
     * @description 查询menu 结果是tree的形式
     * @author zhangyiheng
     * @date 2024/9/4 16:39
     */
    @Override
    public RoutersVo selectRouterMenuTreeByManagerId(ManagerEntity manager) {
        MenuDao mapper = getBaseMapper();
        Long managerId = manager.getManagerId();
        List<MenuVo> menus;
        //判断是否是admin
        if (SecurityUtils.isAdmin(managerId)) {
            //如果是 获取所有符合要求的Menu
            menus = mapper.selectAllRouterMenu();
        } else {
            //否则  获取当前人员所具有的Menu
            menus = mapper.selectRouterMenuTreeByUserId(managerId);
        }
        //构建tree并排序
        return menu2MenuAndRoute(menus);
    }

    private RoutersVo menu2MenuAndRoute(List<MenuVo> list) {
        Map<Long, MenuVo> all = new HashMap<>();
        List<MenuVo> tree = new ArrayList<>();
        List<Route> routes = new ArrayList<>();
        for (MenuVo menu : list) {
            if (menu.getParentId() == 0) {
                tree.add(menu);
            }
            all.put(menu.getId(), menu);
            if (menu.getPath() != null) {
                routes.add(new Route(menu.getPath(), menu.getComponent(), menu.getName()));
            }
        }

        for (MenuVo menu : list) {
            MenuVo parent = all.get(menu.getParentId());
            if (parent != null) {
                List<MenuVo> children = parent.getChildren();
                if (children == null) {
                    children = new ArrayList<>();
                    parent.setChildren(children);
                }
                children.add(menu);
            }
        }
        return new RoutersVo(tree, routes);
    }

    private List<MenuVo> builderMenuTree(List<MenuVo> menus) {
        Map<Long, MenuVo> map = new HashMap<>();

        for (MenuVo vo : menus) {
            map.put(vo.getId(), vo);
        }

        List<MenuVo> menuVos = new ArrayList<>();

        for (MenuVo value : map.values()) {
            MenuVo fatherMenu = map.get(value.getParentId());

            if (!Objects.isNull(fatherMenu)) {
                //说明有父分类
                if (CollUtil.isEmpty(fatherMenu.getChildren())) {
                    fatherMenu.setChildren(new ArrayList<>());
                }
                fatherMenu.getChildren().add(value);
                //排序
                categorySonSort(fatherMenu.getChildren());
            } else {
                menuVos.add(value);
                categorySonSort(menuVos);
            }
        }
        return menuVos;
    }

    private void categorySonSort(List<MenuVo> children) {
        children.sort(new Comparator<MenuVo>() {
            @Override
            public int compare(MenuVo o1, MenuVo o2) {
                return (o1.getOrderNum() == null ? 0 : o1.getOrderNum()) - (o2.getOrderNum() == null ? 0 : o2.getOrderNum());
            }
        });
    }

    /**
     * @param status
     * @param menuName
     * @return com.yufubao.framework.result.ResponseResult
     * @description 查询所有菜单父子列表
     * @author zhangyiheng
     * @date 2024/9/12 16:43
     */
    @Override
    public ResponseResult menuParentChildList(String status, String menuName) {
        LambdaQueryWrapper<MenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(menuName), MenuEntity::getMenuName, menuName);
        wrapper.eq(StringUtils.hasText(status), MenuEntity::getStatus, status);
        wrapper.orderByAsc(MenuEntity::getParentId, MenuEntity::getOrderNum);
        List<MenuEntity> menuList = list(wrapper);

        List<MenuVo> menuVos = CopyBean.copyBeanList(menuList, MenuVo.class);

        //构建tree并排序
        return ResponseResult.okResult(builderMenuTree(menuVos));
    }

    /**
     * @param saveMenuDto
     * @return com.yufubao.framework.result.ResponseResult
     * @description 新增菜单
     * @author zhangyiheng
     * @date 2024/9/12 17:07
     */
    @Override
    @Transactional
    public ResponseResult saveMenu(SaveMenuDto saveMenuDto) {
        MenuEntity menu = CopyBean.copyBean(saveMenuDto, MenuEntity.class);
        save(menu);
        return ResponseResult.ok();
    }

    /**
     * @param id
     * @return com.yufubao.framework.result.ResponseResult
     * @description 菜单修改前回显
     * @author zhangyiheng
     * @date 2024/9/12 17:15
     */
    @Override
    public ResponseResult rowBackMenu(Long id) {
        MenuEntity menu = this.getById(id);
        return ResponseResult.okResult(menu);
    }

    /**
     * @param updateMenuDto
     * @return com.yufubao.framework.result.ResponseResult
     * @description 修改菜单
     * @author zhangyiheng
     * @date 2024/9/12 17:20
     */
    @Override
    @Transactional
    public ResponseResult updateMenu(UpdateMenuDto updateMenuDto) {
        if (updateMenuDto.getParentId().equals(updateMenuDto.getId())) {
            throw new BaseException(CommonExceptionEnum.XGCDSB.getCode(), StrUtil.format(CommonExceptionEnum.XGCDSB.getMsg(), updateMenuDto.getMenuName()));
        }

        MenuEntity menu = CopyBean.copyBean(updateMenuDto, MenuEntity.class);

        this.updateById(menu);

        return ResponseResult.ok();
    }

    /**
     * @param menuId
     * @return com.yufubao.framework.result.ResponseResult
     * @description 删除菜单
     * @author zhangyiheng
     * @date 2024/9/12 17:25
     */
    @Override
    @Transactional
    public ResponseResult deleteMenuById(Long menuId) {
        long count = this.count(Wrappers.<MenuEntity>lambdaQuery()
                .eq(MenuEntity::getParentId, menuId));

        //如果等于0可以删除
        if (Objects.equals(count, 0L)) {
            this.removeById(menuId);
            return ResponseResult.ok();
        } else {
            throw new BaseException(CommonExceptionEnum.CZZCDBYXSC);
        }
    }

    /**
     * @return com.yufubao.framework.result.ResponseResult<com.yufubao.model.vo.management.sys.MenuTreeSelectVO>
     * @description 获取菜单树接口
     * @author zhangyiheng
     * @date 2024/9/12 18:46
     */
    @Override
    public ResponseResult treeselect() {
        List<MenuTreeSelectVO> treeSelectVO = menuDao.treeselect();
        return ResponseResult.okResult(treeSelectVO);
    }


    /**
     * @param id
     * @return com.yufubao.framework.result.ResponseResult<com.yufubao.model.vo.management.sys.RoleMenuTreeselectVO>
     * @description 加载对应角色菜单列表树接口
     * @author zhangyiheng
     * @date 2024/9/12 19:03
     */
    @Override
    public RoleMenuTreeselectVO roleMenuTreeselect(Long id) {

        //取树结构
        List<MenuTreeSelectVO> treeselectMap = getBaseMapper().roleMenuTreeselect();

        //取权限对应id
        List<Long> checkedKeys = getBaseMapper().checkedKeys(id);

        //封装数据
        RoleMenuTreeselectVO roleMenuTreeselectVO = new RoleMenuTreeselectVO();
        roleMenuTreeselectVO.setMenus(treeselectMap);
        roleMenuTreeselectVO.setCheckedKeys(checkedKeys);
        return roleMenuTreeselectVO;
    }
}